package com.socket.clientsocket
{
	import com.common.stdlib.ArrayUtil;
	import com.common.stdlib.Memory;
	import com.common.utils.Debug;
	import com.global.GlobalDef;
	import com.liangzhong.global.CMD_Head;
	
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.events.TimerEvent;
	import flash.net.Socket;
	import flash.utils.ByteArray;
	import flash.utils.Timer;
	
	import lz.controls.Alert;
	
	/**
	 * 
	 * @author liangxuhu
	 * 
	 */	
	public class ClientSocket implements IClientSocket
	{
		/**
		 * 关闭方式
		 */		
		protected var closeByServer                   :Boolean;		
		/**
		 *连接状态 
		 */		
		protected var socketState                     :uint;		
		/**
		 *主回调接口 
		 */		
		protected var clientSocketCallBack            :IClientSocketHandler;
		/**
		 * 子回调接口
		 */		
		protected var socketRecvs                     :Array = [];	
		
		/**
		 * 连接
		 */		
		protected var socket                          :Socket;  
		/**
		 *接收长度 
		 */		
		protected var recvSize                        :int;  
		/**
		 *接收缓冲 
		 */		
		protected var recvBuf                         :ByteArray;
		/**
		 *心跳定时器 
		 */		
		protected var detectSocketTimer               :Timer;  

		/**
		 * 接收计数
		 */		
		protected var recvPacketCount                 :uint;	 

		public function ClientSocket()
		{
			recvSize           = 0;
			recvPacketCount    = 0;
			closeByServer      = false;
			
			recvBuf            = ArrayUtil.newLitteEndianByteArray();
			socketState        = SocketState.SocketState_NoConnect;
			detectSocketTimer  = new Timer(30000);
			detectSocketTimer.addEventListener("timer", onHandlerTimer);
			detectSocketTimer.start();
		}
		/**
		 * IClientSocket客户端网络接口  设置回调接口
		 * @param clientSocketHandler
		 * @return 
		 * 
		 */		
		public function setClientSocketCallBack(clientSocketHandler:IClientSocketHandler):Boolean
		{
			clientSocketCallBack = clientSocketHandler;
			return clientSocketCallBack != null;
		}
		/**
		 * 获取回调接口
		 * @return 
		 * 
		 */		
		public function getClientSocketCallBack():IClientSocketHandler
		{
			return clientSocketCallBack;
		}
		/**
		 * 添加回调接口
		 * @param clientSocketHandler
		 * @return 
		 * 
		 */		
		public function addClientSocketHandler(clientSocketHandler:IClientSocketHandler):Boolean
		{
			socketRecvs.push(clientSocketHandler);
			return true;
		}
		/**
		 * 删除回调接口
		 * @param clientSocketHandler
		 * @return 
		 * 
		 */		
		public function removeClientSocketHandler(clientSocketHandler:IClientSocketHandler):Boolean
		{
			for(var i:int = 0; i < socketRecvs.length; i ++)
			{
				if(socketRecvs[i] == clientSocketHandler)
				{
					socketRecvs.splice(i,1);
					return true;
				}
			}	
			return false;
		}
		/**
		 * 删除所有回调接口
		 * 
		 */		
		public function removeAllClientSocketHandler():void
		{
			for(var i:int = 0; i < socketRecvs.length; i ++)
			{
				socketRecvs[i] = null;
			}	
			socketRecvs = [];
		}
		/**
		 * 获取状态
		 * @return 
		 * 
		 */		
		public function get connectState():int
		{
			return socketState;
		}
		/**
		 *设置数据加密密钥 
		 * @param packetKey
		 * 
		 */		
		public function set packetKey(packetKey:uint):void
		{
			
		}
		/**
		 *连接服务器 
		 * @param serverIP
		 * @param port
		 * @return 
		 * 
		 */		
		public function connect(serverIP:String,port:int):Boolean
		{
			if (socket != null)
			{
				trace("Socket Connected");
				throw new Error("Socket Connected");
				return false;
			}
			socket=new Socket();
			socket.timeout = 60000;
			configureListeners();
			if (socket.connected)
			{
				trace("Socket Connected");
				throw new Error("Socket Connected");
				return false;
			}
			var myDate1:Date=new Date;

			recvSize=0;
			
			socket.connect(serverIP,port);
			socketState = SocketState.SocketState_Connecting;
			
			return true;
		}
		/**
		 *发送函数 (只发送命令，比如用在一些验证用户是否还在线的检测)
		 * @param mainCmdID
		 * @param subCmdID
		 * @return 
		 * 
		 */		
		public function sendCmd(mainCmdID:int,subCmdID:int):Boolean
		{
			//效验状态
			if (socket == null)
			{
				trace("SendCmd socket == null");
				return false;
			}
			if (socketState != SocketState.SocketState_Connected)
			{
				trace("SendCmd socketState != SocketState_Connected");
				return false;
			}

			//构造数据
			var dataBuffer :ByteArray = new ByteArray();


			//发送数据
			return sendBuffer(dataBuffer,dataBuffer.length);
		}
		/**
		 * 
		 * @param mainCmdID
		 * @param subCmdID
		 * @param data
		 * @param dataSize
		 * @return 
		 * 
		 */		
		public function sendData(data:ByteArray,dataSize:int):Boolean
		{
			//效验状态
			if (socket == null)
			{
				return false;
			}
			if (socketState != SocketState.SocketState_Connected)
			{
				return false;
			}
			//效验大小
			

			//构造数据
			

			//发送数据
			return sendBuffer(data,data.length);
		}
		/**
		 *关闭连接 
		 * @param bNotify
		 * @return 
		 * 
		 */		
		public function closeSocket(bNotify:Boolean):Boolean
		{
			socketState = SocketState.SocketState_NoConnect;
			if (socket != null)
			{
				detectSocketTimer.stop();
				try
				{
					socket.close();
				}
				catch(e:Error)
				{
					//trace(e.getStackTrace());
				}
				var cflag :Boolean = false;
				if (bNotify == true)
				{

					try
					{
						if(clientSocketCallBack != null)
						{
							cflag = clientSocketCallBack.onSocketClose(this,closeByServer);
						}
						if(cflag == false)
						{
							for(var i:int = 0;i < socketRecvs.length; i ++)
							{
								cflag = socketRecvs[i].onSocketClose(this as IClientSocket, bNotify);
								if(cflag)
								{
									break;
								}
							}
						}
					}
					catch (e:Error)
					{
						trace(e.getStackTrace());
					}
				}
			}
			//恢复数据
			recvSize=0;
			recvPacketCount=0;
			closeByServer=false;
			deconfigureListeners();
			socket = null;
			return true;
		}
		/**
		 *配置监听器 
		 * 
		 */		
		private function configureListeners():void
		{
			socket.addEventListener(Event.CLOSE,onHandlerSocketClose);
			socket.addEventListener(Event.CONNECT,onHandlerConnect);
			socket.addEventListener(IOErrorEvent.IO_ERROR,onHandlerIoError);
			socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onHandlerSecurityError);
			socket.addEventListener(ProgressEvent.SOCKET_DATA,onHandlerSocketData);
		}
		/**
		 *取消配置监听器 
		 * 
		 */		
		private function deconfigureListeners():void
		{
			if (socket != null)
			{
				socket.removeEventListener(Event.CLOSE,onHandlerSocketClose);
				socket.removeEventListener(Event.CONNECT,onHandlerConnect);
				socket.removeEventListener(IOErrorEvent.IO_ERROR,onHandlerIoError);
				socket.removeEventListener(SecurityErrorEvent.SECURITY_ERROR,onHandlerSecurityError);
				socket.removeEventListener(ProgressEvent.SOCKET_DATA,onHandlerSocketData);
			}
		}
		
		/**
		 * 发送数据
		 * @param buffer
		 * @param sendSize
		 * @return 
		 * 
		 */		
		private function sendBuffer(buffer:ByteArray,sendSize:int):Boolean
		{
			socket.writeBytes(buffer);
			socket.flush();
			return true;
		}
		
		/**
		 * 网络关闭事件
		 * @param event
		 * 
		 */		
		private function onHandlerSocketClose(event:Event):void
		{
			trace("onHandlerSocketClose: " + event);
			closeByServer=true;
			closeSocket(true);
		}
		/**
		 * 网络连接事件
		 * @param event
		 * 
		 */		
		private function onHandlerConnect(event:Event):void
		{
			trace("onHandlerConnect: " + event);
			
			socketState = SocketState.SocketState_Connected
			var success:Boolean = false;
			//处理数据
			if (clientSocketCallBack)
			{
				success = clientSocketCallBack.onSocketConnect(0,"",this);
			}
			if (success == false)
			{
				var recv :IClientSocketHandler;
				
				for(var i:int = 0;i < socketRecvs.length; i ++)
				{
					recv = socketRecvs[i];
					success = recv.onSocketConnect(0,"",this);
					if(success)
					{
						break;
					}
				}
			}
		}
		/**
		 *网络错误事件 
		 * @param event
		 * 
		 */		
		private function onHandlerIoError(event:IOErrorEvent):void
		{
			trace("onHandlerIoError: " + event);
			Alert.show("网络连接超时 0","",Alert.YES,GlobalDef.GameStage);
			closeByServer=true;
			if(clientSocketCallBack)
			{
				clientSocketCallBack.onSocketError(this,event);
			}
		}
		/**
		 *网络安全错误事件 
		 * @param event
		 * 
		 */		
		private function onHandlerSecurityError(event:SecurityErrorEvent):void
		{
			trace("onHandlerSecurityError: " + event);
			Alert.show("网络连接超时 1","",Alert.YES,GlobalDef.GameStage);
			closeByServer=true;
			if(clientSocketCallBack)
			{
				clientSocketCallBack.onSocketError(this,event);
			}
		}
		/**
		 *数据事件通知 
		 * @param event
		 * 
		 */		
		private function onHandlerSocketData(event:ProgressEvent):void
		{
			var dLen :int = socket.bytesAvailable;
			Debug.echo("receive buffer size = " + dLen + ",last leave size = " + recvSize,Debug.TRACER);
			socket.readBytes(recvBuf,recvSize);
			recvSize += dLen;
			var success :Boolean = false;
			while(true)
			{
				if(recvBuf.bytesAvailable < CMD_Head.Size)
				{
					return;
				}
				var oldPos :int = recvBuf.position;
				var cmd_Head :CMD_Head = CMD_Head.readData(recvBuf);
				if((cmd_Head.dataLen - CMD_Head.Size) > recvBuf.bytesAvailable)
				{
					recvBuf.position = oldPos;
					return;
				}
				if(cmd_Head.dataLen == 0)
				{
					Debug.echo("cmd_Head.dataLen == 0",Debug.TRACER);
					return;
				}
				Debug.echo("Head: ServerType = "+cmd_Head.serverType+" methodId = "+cmd_Head.methodId+" Length = "+cmd_Head.dataLen,Debug.TRACER);
				var dstByteArray :ByteArray = ArrayUtil.newLitteEndianByteArray();
				if((cmd_Head.dataLen - CMD_Head.Size) > 0)
				{
					recvBuf.readBytes(dstByteArray,0,(cmd_Head.dataLen - CMD_Head.Size));
				}
				recvSize -= cmd_Head.dataLen;
				var tempDstByteArray :ByteArray = ArrayUtil.newLitteEndianByteArray();
				recvBuf.readBytes(tempDstByteArray);
				recvBuf.clear();
				Memory.moveMemory(recvBuf,tempDstByteArray,tempDstByteArray.bytesAvailable,0,0);
				success = onSocketRead(cmd_Head.serverType,cmd_Head.methodId,dstByteArray,cmd_Head.dataLen,this);
				if(success == false)
				{
					Debug.echo("Not deal package：ServerType："+cmd_Head.serverType+" methodId:"+cmd_Head.methodId,Debug.TRACER);
				}
			}
		}
		/**
		 *定时器事件 
		 * @param e
		 * 
		 */		
		private function onHandlerTimer(e:TimerEvent):void
		{
			if(socket != null && 
			   socket.connected)
			{
				var sendBuf :ByteArray = 
					CMD_Head.getHeadByteArrayBuff(CMD_Head.Size ,1,999,0);
				sendBuf.position = 0;
				this.sendData(sendBuf,sendBuf.bytesAvailable);
			}
		}
		/**
		 *网络读取消息 
		 * @param mainCmdID
		 * @param subCmdID
		 * @param buffer
		 * @param dataSize
		 * @param clientSocket
		 * @return 
		 * 
		 */		
		protected function onSocketRead(mainCmdID:uint,
										subCmdID:uint,
										buffer:ByteArray,
										dataSize:int,
										clientSocket:IClientSocket):Boolean
		{
			var success:Boolean = false;
			//处理数据
			if (clientSocketCallBack)
			{
				success = clientSocketCallBack.onSocketRead(mainCmdID,subCmdID,buffer,dataSize,clientSocket);
			}
			if (success == false)
			{
				var recv :IClientSocketHandler;

				for(var i:int = 0;i < socketRecvs.length; i ++)
				{
					recv = socketRecvs[i];
					success = recv.onSocketRead(mainCmdID,subCmdID,buffer,dataSize, clientSocket);
					if(success)
					{
						break;
					}
				}
			}
			
			return success;
		}

	}
}